package DyingBaby.utils;

import com.google.common.primitives.Bytes;

import java.nio.ByteBuffer;
import java.util.Arrays;

public class Parser {


    /**
     * 这段代码是一个Java方法，用于将short类型的数据转换为byte数组。这里使用了ByteBuffer来实现这个转换。
     *
     * 1. `ByteBuffer.allocate(Short.SIZE / Byte.SIZE)`：创建一个新的ByteBuffer实例，分配两个字节的空间。因为Short.SIZE通常为16（Java中short类型占16位），而Byte.SIZE为8，所以分配的空间足够存储一个short类型的数据。
     *
     * 2. `.putShort(value)`：将传入的short类型数值value写入ByteBuffer。
     *
     * 3. `.array()`：将ByteBuffer转换为byte数组。由于ByteBuffer已经包含了我们写入的short类型数据，调用此方法会返回包含转换后数据的byte数组。
     *
     * 总的来说，这个方法的作用就是将一个short型数值转换成一个长度为2的byte数组。在Little-Endian系统中，这个byte数组的前两个字节将分别表示short数值的低位和高位。在Big-Endian系统中则相反。
     */

    public static byte[] short2Byte(short value) {
        return ByteBuffer.allocate(Short.SIZE / Byte.SIZE).putShort(value).array();
    }


    /**
     * 这个Java方法用于从一个长度为2的字节数组`buf`中解析出一个short类型数值。
     *
     * 1. `ByteBuffer.wrap(buf, 0, 2)`：创建一个ByteBuffer实例，它包装了传入的字节数组`buf`的部分区域，从索引0开始，长度为2。这意味着ByteBuffer将会处理数组的前两个字节。
     *
     * 2. `buffer.getShort()`：从ByteBuffer中读取一个short类型数值。ByteBuffer会按照其内部的字节顺序（默认是平台相关的，可以通过order()方法设置）来解析这两个字节，还原成一个short类型的数值。
     *
     * 因此，整个`parseShort`方法的功能就是从给定的包含两个字节的数组中解码出一个short类型的数值。如果字节数组不是按照正确的字节序存放的short值，那么解析出来的结果可能会不正确。
     */
//    parseShort()与short2Byte()方法为一对，short2Byte()将short类型数值转化为byte数组，而parseShort()将byte数组转化为short类型数值
    public static short parseShort(byte[] buf) {
        ByteBuffer buffer = ByteBuffer.wrap(buf, 0, 2);
        return buffer.getShort();
    }

    public static byte[] int2Byte(int value) {
        return ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).putInt(value).array();
    }

    public static int parseInt(byte[] buf) {
        ByteBuffer buffer = ByteBuffer.wrap(buf, 0, 4);
        return buffer.getInt();
    }

    public static long parseLong(byte[] buf) {
        ByteBuffer buffer = ByteBuffer.wrap(buf, 0, 8);
        return buffer.getLong();
    }

    public static byte[] long2Byte(long value) {
        return ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(value).array();
    }

    public static ParseStringRes parseString(byte[] raw) {
        int length = parseInt(Arrays.copyOf(raw, 4));
        String str = new String(Arrays.copyOfRange(raw, 4, 4+length));
        return new ParseStringRes(str, length+4);
    }

    public static byte[] string2Byte(String str) {
        byte[] l = int2Byte(str.length());
        return Bytes.concat(l, str.getBytes());
    }

    /**
     *
     * 这段Java代码定义了一个名为str2Uid的方法，它的功能是将输入的字符串key转换为一个长整型数字（uid）。实现方式是对字符串的每一个字节进行哈希运算。
     *
     * 首先，初始化一个名为seed的长整型变量，值为13331。这个种子值在每次迭代中都会被用来参与到哈希计算中。
     *
     * 初始化一个名为res的长整型变量，作为最终结果，初始值为0。
     *
     * 使用增强for循环遍历字符串key经过getBytes()方法转换得到的字节数组。对于数组中的每个字节b：
     *
     * 将当前的结果res乘以种子值seed。
     * 然后将得到的乘积加上字节b转换为长整型后的值。
     * 循环结束后，res变量将累积所有字节参与运算的结果，最后返回这个累积值作为字符串key对应的uid。
     *
     * 这种方法实现的字符串到uid的映射并不具备通用哈希函数的一些理想属性，比如均匀分布和抗碰撞性，仅可用于简单且非安全敏感的场景。在需要高质量哈希函数的场合，请考虑使用标准库提供的Hash函数或者专门设计的哈希算法。
     *
     */

    public static long str2Uid(String key) {
        long seed = 13331;
        long res = 0;
        for(byte b : key.getBytes()) {
            res = res * seed + (long)b;
        }
        return res;
    }

}
